跳到主要内容

HCL 语法速查

本篇收录写 Terraform 配置时最常用的 HCL 类型字面量、内置函数和条件循环写法,适用于 Terraform 1.9+。

类型字面量​

类型写法示例说明
string"nginx"双引号包裹,内部支持 ${} 插值
number8080、3.14整数浮点同属 number,自动推导
booltrue / false不加引号
list["a", "b", "c"]有序可重复,索引从 0 开始
settoset(["a", "b"])无序不重复,无字面量写法,需 toset() 转换
map{ "env" = "prod", "team" = "ops" }键值对,键统一为字符串
object{ name = "web", ports = [80, 443] }带固定属性的结构体,各属性类型可不同

常用函数​

函数作用示例
join把列表按分隔符拼成字符串join(",", ["a", "b"]) → "a,b"
split按分隔符把字符串切成列表split(",", "a,b") → ["a", "b"]
concat拼接多个列表为一个concat([1], [2, 3]) → [1, 2, 3]
merge合并多个 map,后者覆盖前者同名键merge({ a = 1 }, { b = 2 }) → { a = 1, b = 2 }
lookup按键查 map,查不到返回默认值lookup(var.sizes, "prod", "small")
length返回字符串、列表或 map 的长度length(var.subnets)
keys取 map 全部键,组成列表keys(var.tags)
values取 map 全部值,组成列表values(var.tags)
format按格式串生成字符串,类似 printfformat("%s-%02d", "web", 1) → "web-01"
file读取本地文件内容为字符串file("${path.module}/user_data.sh")
templatefile渲染模板文件并注入变量templatefile("init.tpl", { pkg = "nginx" })
try依次尝试多个表达式,返回首个不报错的结果try(var.cfg.port, 8080)
coalesce返回首个非 null 的参数coalesce(var.name, "default")
can判断表达式能否正常求值,返回 boolcan(regex("^ami-", var.ami_id))
contains判断列表是否包含某元素contains(var.azs, "cn-north-1a")
distinct列表去重,保持原有顺序distinct(["a", "a", "b"]) → ["a", "b"]
flatten把嵌套列表拍平为一层flatten([[1, 2], [3]]) → [1, 2, 3]
try 与 can 的分工

try 拿值:一连串取值路径哪个通用哪个。can 判真假:常塞在 validation 块或条件表达式里做前置校验。两者都不会因表达式报错中断执行。

条件与循环​

写法适用场景示例
三元 + count按条件决定资源建不建count = var.enable_monitor ? 1 : 0
for_each + map按 map 批量建资源,键稳定、可单独寻址for_each = var.instances,资源内用 each.key、each.value
for 表达式对列表/map 做转换、过滤,生成新集合见下方代码块

for 表达式的三种典型形态:

# 列表推导:取出所有实例的私网 IP
private_ips = [for inst in aws_instance.web : inst.private_ip]

# map 推导:键值同时转换
upper_tags = { for k, v in var.tags : k => upper(v) }

# 带 if 过滤:只保留生产环境的子网 ID
prod_subnets = [for s in var.subnets : s.id if s.env == "prod"]
for_each 为什么优先用 map

for_each 接受 map 或 set of string。用 map 时每个实例以 each.key 作为状态地址的一部分,增删元素不影响其他实例;用 list 转 set 则元素一变地址全乱,容易触发大面积重建。

注释与多行字符串​

# 单行注释(推荐风格)

// 单行注释(与 # 等价)

/*
多行块注释,
可跨任意行数
*/

# heredoc 多行字符串,${ } 插值照常生效
user_data = <<-EOF
#!/bin/bash
yum install -y ${pkg_name}
systemctl enable --now ${pkg_name}
EOF
  • <<EOF 原样保留内容;<<-EOF 允许内容缩进对齐,输出时自动去掉公共前导空白,配置里优先用带横线的写法
  • heredoc 结束标记必须顶格独占一行,中间内容里的 ${} 会按 Terraform 表达式求值